﻿using System;
using NUnit.Framework;
using SimpleServiceBus.Bus;
using SimpleServiceBus.Bus.MessageManagement.MessageHandling;
using SimpleServiceBus.Bus.Pipeline;
using SimpleServiceBus.Tests.Stubs;
using SimpleServiceBus.Utilities.ObjectBuilder;

namespace SimpleServiceBus.Tests.Bus.MessageManagement.MessageHandling
{
    [TestFixture]
    public class DefaultMessageDispatcherTestFixture
    {
        #region Setup/Teardown

        [SetUp]
        public void TestSetUp()
        {
            TestHandler_A.Handled = false;
            TestHandler_B.Handled = false;
            TestHandler_C.Handled = false;
        }

        #endregion

        private ServiceLocatorOnlyMessageContext _messageContext;
        private IMessageHandlerResolutionService _resolver;


        [TestFixtureSetUp]
        public void SetUp()
        {
            _messageContext = new ServiceLocatorOnlyMessageContext();
            _messageContext.RegisterService<IObjectBuilderService, DefaultObjectBuilderService>();
            _resolver =
                _messageContext.RegisterService
                    <IMessageHandlerResolutionService, DefaultMessageHandlerResolutionService>();

            _resolver.RegisterMessageHandler(typeof (TestHandler_A));
            _resolver.RegisterMessageHandler(typeof (TestHandler_B));
            _resolver.RegisterMessageHandler(typeof (TestHandler_C));
        }

        [Test]
        public void Dispatch_To_Handlers_Respect_Abort_Flag()
        {
            var dispatcher = new DefaultMessageDispatcher();
            string message = Guid.NewGuid().ToString();

            dispatcher.Dispatch(new MessageEnvelope {Body = message}, _messageContext);

            Assert.IsTrue(TestHandler_A.Handled);
            Assert.AreEqual(TestHandler_A.Message, message);

            Assert.IsTrue(TestHandler_B.Handled);
            Assert.AreEqual(TestHandler_B.Message, message);

            Assert.IsFalse(TestHandler_C.Handled);
        }
    }

    public class TestHandler_A : IMessageHandler<string>
    {
        public static bool Handled;
        public static string Message;

        #region IMessageHandler<string> Members

        public void Handle(string message, IMessageContext context)
        {
            Handled = true;
            Message = message;
        }

        #endregion
    }

    public class TestHandler_B : IMessageHandler<string>
    {
        public static bool Handled;
        public static string Message;

        #region IMessageHandler<string> Members

        public void Handle(string message, IMessageContext context)
        {
            Handled = true;
            Message = message;

            context.AbortMessageProcessing = true;
        }

        #endregion
    }

    public class TestHandler_C : IMessageHandler<string>
    {
        public static bool Handled;

        #region IMessageHandler<string> Members

        public void Handle(string message, IMessageContext context)
        {
            Handled = true;
        }

        #endregion
    }
}